package models

import (
	"fmt"
	"database/sql"
	"smallstory/datasource"
	"time"
	"smallstory/config"
)

type Story struct {
	Id         int    `json:"id"`
	Title      string `json:"title"`
	User       User   `json:"user"`
	Createdate int64  `json:"createdate"`
	Tag        string `json:"tag"`
	ChapterNum int    `json:"chapternum"`
}

type Chapter struct {
	User        User   `json:"user"`
	Id          int    `json:"id"`
	Uid         string `json:"uid"`
	Title       string `json:"title"`
	Likecount   string `json:"like"`
	Creatername string `json:"creatername"`
	Sid         int    `json:"sid"`
	Content     string `json:"content"`
	Createdate  int64  `json:"createdate"`
	Key         string `json:"keyword"`
}

type StoryDAO struct {
}

func (storyDao *StoryDAO) FindListByPage() []Story {
	sqlStatement := `SELECT t_story.*,t_user.name, t_user.head, count(t_chapter.id) AS chapterNum
					 FROM t_story,t_chapter,t_user
					 WHERE t_story.id=t_chapter.sid AND t_user.uid=t_story.uid
					 GROUP BY t_story.id ,t_user.name,t_user.head ORDER BY t_story.id DESC LIMIT 10 ;`
	return findAllList(sqlStatement, -1)
}

func (storyDao *StoryDAO) FindNewListByPage(id int) []Story {
	sqlStatement := `SELECT t_story.*,t_user.name, t_user.head, count(t_chapter.id) AS chapterNum
					 FROM t_story,t_chapter,t_user
					 WHERE t_story.id=t_chapter.sid AND t_user.uid=t_story.uid AND t_story.id>$1
					 GROUP BY t_story.id ,t_user.name,t_user.head ORDER BY t_story.id DESC LIMIT 10 ;`
	return findAllList(sqlStatement, id)
}

func (storyDao *StoryDAO) FindListLoadmore(id int) []Story {
	sqlStatement := `SELECT t_story.*,t_user.name, t_user.head, count(t_chapter.id) AS chapterNum
					 FROM t_story,t_chapter,t_user
					 WHERE t_story.id=t_chapter.sid AND t_user.uid=t_story.uid AND t_story.id<$1
					 GROUP BY t_story.id ,t_user.name,t_user.head ORDER BY t_story.id DESC LIMIT 10 ;`
	return findAllList(sqlStatement, id)
}

func findAllList(sqlStatement string, id int) []Story {

	connectInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
		datasource.Host, datasource.Port, datasource.UserName, datasource.Password, datasource.DBname)
	db, err := sql.Open("postgres", connectInfo)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	var rows *sql.Rows

	if id == -1 {
		rows, err = db.Query(sqlStatement)
	} else {
		rows, err = db.Query(sqlStatement, id)
	}

	if err != nil {
		panic(err)
	}
	defer rows.Close()

	stories := [] Story{}
	story := &Story{}

	for rows.Next() {
		rows.Scan(&story.Title, &story.User.Uid, &story.Id,
			&story.Tag, &story.Createdate,
			&story.User.Name, &story.User.HeaderImg, &story.ChapterNum)
		stories = append(stories, *story)
	}

	return stories
}

func (storyDao *StoryDAO) FindChapterListByID(sid int, id int, pageSize int) ([]Chapter, int) {

	connectInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
		datasource.Host, datasource.Port, datasource.UserName, datasource.Password, datasource.DBname)
	db, err := sql.Open("postgres", connectInfo)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	sqlStatement := `SELECT c.*,u.uid,u.name,u.head FROM t_chapter c,t_user u WHERE c.sid=$1 AND c.uid=u.uid AND c.id>$2 ORDER BY c.id  LIMIT $3;`
	var rows *sql.Rows

	if id < 0 {
		sqlStatement = `SELECT c.*,u.uid,u.name,u.head
						FROM t_chapter c,t_user u
						WHERE c.sid=$1 AND c.uid=u.uid  ORDER BY c.id  LIMIT $2;`
		rows, err = db.Query(sqlStatement, sid, pageSize)
	} else {
		rows, err = db.Query(sqlStatement, sid, id, pageSize)
	}

	if err != nil {
		panic(err)
	}
	defer rows.Close()

	chapters := [] Chapter{}
	chapter := Chapter{}
	total := 0

	for rows.Next() {
		rows.Scan(&chapter.Uid, &chapter.Likecount, &chapter.Content, &chapter.Id,
			&chapter.Sid, &chapter.Key, &chapter.Createdate,
			&chapter.User.Uid, &chapter.User.Name, &chapter.User.HeaderImg)
		chapters = append(chapters, chapter)
	}

	return chapters, total
}

func (storyDao *StoryDAO) CreateByUid(uid string, story Story, chapter Chapter) int {

	connectInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
		datasource.Host, datasource.Port, datasource.UserName, datasource.Password, datasource.DBname)
	db, err := sql.Open("postgres", connectInfo)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	tx, _ := db.Begin()

	sqlStatement := `INSERT INTO t_story (title, uid, createdate,tag)  VALUES ($1, $2, $3,$4) RETURNING id`
	sid := 0
	err = tx.QueryRow(sqlStatement, story.Title, uid, story.Createdate, story.Tag).Scan(&sid)
	if err != nil {
		panic(err)
		tx.Rollback()
		return 0
	}

	sqlStatement = `INSERT INTO t_chapter (uid, createdate, content, sid ,key)  VALUES ($1, $2, $3, $4,$5)`
	_, err = tx.Exec(sqlStatement, chapter.Uid, chapter.Createdate, chapter.Content, sid, chapter.Key)

	if err != nil {
		panic(err)
		tx.Rollback()
		return 0
	}

	err = tx.Commit()

	if err != nil {
		panic(err)
		return 0
	}

	return 1
}

func (storyDao *StoryDAO) Add(chapter Chapter) int {

	connectInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
		datasource.Host, datasource.Port, datasource.UserName, datasource.Password, datasource.DBname)
	db, err := sql.Open("postgres", connectInfo)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	sqlStatement := `INSERT INTO t_chapter (uid, createdate, content, sid,key)  VALUES ($1, $2, $3, $4,$5)`
	_, err = db.Exec(sqlStatement, chapter.Uid, chapter.Createdate, chapter.Content, chapter.Sid, chapter.Key)

	if err != nil {
		panic(err)
		return 0
	}

	return 1
}

func (storyDao *StoryDAO) UpdateLikeCount(chapter Chapter) int {

	connectInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
		datasource.Host, datasource.Port, datasource.UserName, datasource.Password, datasource.DBname)
	db, err := sql.Open("postgres", connectInfo)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	//检查点赞的数据是否已经存在
	var cid int
	selectLike := `SELECT cid FROM t_like WHERE uid=$1 AND cid=$2`
	selectErr := db.QueryRow(selectLike, chapter.Uid, chapter.Id).Scan(&cid)

	if selectErr != nil {

		//更新t_chapter的点赞数
		sqlStatement := `UPDATE t_chapter SET likecount=likecount+1  WHERE id=$1`
		_, err = db.Exec(sqlStatement, chapter.Id)
		if err != nil {
			panic(err)
			return config.ERROR
		}

		sqlStatement2 := `INSERT INTO t_like (uid, cid,like_time)  VALUES ($1, $2,$3)`
		_, err = db.Exec(sqlStatement2, chapter.Uid, chapter.Id, time.Now().Local().UnixNano()/1e6)

		return config.SUCCESED

	} else {
		return config.HASBEEN
	}

}
